import { E_BattleUnitAttr, I_ActionMsg, I_SubActionMsg } from "./BattleConst";
import BattleUnit from "./BattleUnit";
import BattleFormula from "./core/BattleFormula";
import BattleUnitBase from "./core/BattleUnitBase";
import SkillBase from "./core/SkillBase";
import { EventId } from "./event/EventId";
import EventMgr from "./event/EventMgr";
import MathUtil from "./util/MathUtil";

/**
 * 战斗数据计算类（真实战斗计算，不做表现）
 */
export default class Combat {
    /**所有单位 */
    units: BattleUnit[];

    /**当前回合数 */
    curRound: number;

    /**行动单位队列(不能行动的也放队列里，做一下不能行动的表现) */
    _actionUnitQueue: BattleUnit[];

    /**当前行动的角色 */
    curUnit: BattleUnit = null;

    /**战斗结束 */
    isBattleEnd: boolean = false;

    constructor() {
        this.units = [];
        this.curRound = 0;
        this.isBattleEnd = false;
        this._actionUnitQueue = [];
        this.curUnit = null;
    }

    init() {
        EventMgr.ins.on(EventId.DO_BATTLE_END, this.doBattleEnd, this)
        //加入战斗单位(加入数据，形象通知BattleManger加到场景)
        let player = new BattleUnit({ uid: "1001", group: 1, pos: { x: -300, y: -200 } })
        player.attrMgr.setInitAttrs({
            [E_BattleUnitAttr.ATK]: 10,
            [E_BattleUnitAttr.DEFENSE]: 5,
            [E_BattleUnitAttr.CRITICAL_RATE]: 5000,
            [E_BattleUnitAttr.IGNORE_CRITICAL_RATE]: 1000,
            [E_BattleUnitAttr.SPEED]: 100,
            [E_BattleUnitAttr.HP]: 100,
            [E_BattleUnitAttr.DODGE_RATE]: 1000,
            [E_BattleUnitAttr.IGNORE_DODGE_RATE]: 10000,
        });
        player.dic = 1;
        this.units.push(player)
        EventMgr.ins.event(EventId.ADD_ROLE, player);

        let player2 = new BattleUnit({ uid: "1002", group: 2, pos: { x: 300, y: -200 } })
        player2.attrMgr.setInitAttrs({
            [E_BattleUnitAttr.ATK]: 10,
            [E_BattleUnitAttr.DEFENSE]: 5,
            [E_BattleUnitAttr.CRITICAL_RATE]: 5000,
            [E_BattleUnitAttr.IGNORE_CRITICAL_RATE]: 1000,
            [E_BattleUnitAttr.SPEED]: 100,
            [E_BattleUnitAttr.HP]: 100,
            [E_BattleUnitAttr.DODGE_RATE]: 1000,
            [E_BattleUnitAttr.IGNORE_DODGE_RATE]: 10000,
        });
        player2.dic = -1;
        this.units.push(player2)
        EventMgr.ins.event(EventId.ADD_ROLE, player2);
        //所有单位加入完后战斗开始
        setTimeout(this.combatStart.bind(this), 2000)
    }

    /**战斗开始 */
    public combatStart() {
        for (let e of this.units) {
            e.onCombatStart();
        }
        this.roundBegin();
    }

    /**一轮开始（把所有单位按速度排序） */
    public roundBegin() {
        this.curRound += 1;
        this._actionUnitQueue = this.units.concat();
        //排序
        this._sortActionQueue();
        //触发一下所有角色的buff（有的buff效果在回合开始触发）
        for (let e of this.units) {
            e.onRoundBegin();
        }
        this.roundAction()
    }

    /**回合行动（选择出手的单位） */
    private roundAction(): void {
        this.curUnit = this._actionUnitQueue[0];
        if (this.curUnit) {
            this.curUnit.startAction();
            this.unitAction();
        } else {
            this.roundEnd()
        }
    }

    /**行动结束 */
    private doBattleEnd(): void {
        this._actionUnitQueue.shift();
        this.roundAction();
    }

    /**正常流程-打开操作面板（攻击-技能-防御-道具-休息）自动战斗-随机选择技能-随机选择目标 */
    private unitAction(): void {
        if (1) {//先做自动操作
            let skill: SkillBase = this.curUnit.skillMgr.getRandomSkill(this.curUnit);
            let targets: BattleUnit[] = this.getTargets(this.curUnit, skill);
            //一次行动的结果
            const result: I_ActionMsg = this.getBattleResut(this.curUnit, targets, skill)
            console.log("一次行动结果", result)
            //把结果给界面展示，等动画展示完下一个人行动，这里直接下一个人行动
            EventMgr.ins.event(EventId.DO_BATTLE, result);
        } else {

        }
    }

    private getBattleResut(cast: BattleUnit, targets: BattleUnit[], skill: SkillBase): I_ActionMsg {
        const result: I_ActionMsg = {
            action: cast,
            targets: targets,
            subActions: []
        }
        targets.forEach(t => {
            const oneRes: I_SubActionMsg = {
                action: cast,
                target: t,
                subActionType: 1,
                attackDic: 50
            }
            //根据施法者和目标得出命中率
            let hitRate = BattleFormula.getCurHitRate(cast, t);
            let isHit = MathUtil.rateBingo(hitRate);
            if (isHit) {
                oneRes.isMiss = false;
                //根据攻击和防御算出来得基础伤害值
                let damage = BattleFormula.getNormalHurt(cast, t);
                //暴击
                let isCrit = MathUtil.rateBingo(BattleFormula.getCritical(cast, t));
                if (isCrit) {
                    damage = BattleFormula.getCriticalHurt(damage, cast, t);
                }
                oneRes.critical = isCrit;
                //属性克制之类

                //触发伤害追加类buff（如暴击增伤、破盾增伤）

                //攻击方增伤buff
                damage = BattleFormula.hurtAdd(damage, cast);
                //受击方减伤buff
                damage = BattleFormula.hurtReduce(damage, t);
                //是否需要计算护盾值(无视护盾、真伤类不需要计算护盾)
                let shield = 0;
                //是否破盾
                let isBreakShield = false;
                if (1) {
                    //受击方护盾值
                    shield = t.attrMgr.getAttr(E_BattleUnitAttr.SHIELD);
                    //受击方是否有护盾
                    t.cutShield(Math.min(shield, damage));
                    isBreakShield = damage >= shield;
                }

                //触发技能携带的buff（如概率眩晕、流血、毒）

                //触发攻击方身上的buff（武器、衣服、圣物）

                //触发受击方buff

                //受击方扣血(把护盾值去掉再扣血)
                t.hurt(Math.max(0, damage - shield));
                oneRes.hurtNum = damage;
            } else {
                oneRes.isMiss = true;
            }
            console.warn(`施法者${cast.uid},受击方${t.uid},是否命中${isHit},是否暴击${oneRes.critical},造成伤害${oneRes.hurtNum}`)
            result.subActions.push(oneRes);
        })
        return result
    }


    /**根据行动角色和选择技能选中目标 */
    private getTargets(unit: BattleUnit, skill: SkillBase): BattleUnit[] {
        let targets: BattleUnit[] = [];
        let count = skill ? skill?.targetCount : 1;
        if (count == -1) {//全部敌人或全部队友
            for (let e of this.units) {
                if (!e.isAlive()) continue; //后面再处理复活技能
                if (e.unitGroup != unit.unitGroup) {
                    targets.push(e);
                }
            }
        } else {
            for (let e of this.units) {
                if (count <= 0) break;
                if (!e.isAlive()) continue; //后面再处理复活技能
                if (e.unitGroup != unit.unitGroup) {
                    targets.push(e);
                    count--;
                }
            }
        }
        return targets;
    }

    /**一轮结束 */
    roundEnd(): void {
        for (let e of this.units) {
            e.onRoundEnd();
        }
        for (let e of this.units) {
            if (e.attrMgr.getAttr(E_BattleUnitAttr.HP) <= 0) {
                console.log("一方死亡，结束");
                return;
            }
        }
        //开始下一轮
        this.roundBegin()
    }

    /**根据速度对行动角色排序 */
    private _sortActionQueue() {
        this._actionUnitQueue.sort((a, b) => {
            return a.attrMgr.getAttr(E_BattleUnitAttr.SPEED) - b.attrMgr.getAttr(E_BattleUnitAttr.SPEED)
        })
    }
}